import { loadScript } from '@/utils'
import '@/css/bnmap.css'

/**
 * @description 博能地图插件
 */
/**
 * @description 博能地图插件
 */
class CyMapBNPlugin {
    /**
     * 实例化
     * @param {CyMapOption} option 地图类的配置项
     */
    constructor(option = {}) {
        this.option = option
        this.loadedScript = false // 是否加载过脚本
        this.bnMap = null // 地图实例
        this.watingAction = []
        this.pointLayerID = option.pointLayerID || 'points' // 点位图层 ID
        this.pointSourceID = option.pointSourceID || 'points' // 点位数据源 ID
        this.pointGeojson = { type: 'FeatureCollection', features: [] }
        this.pointIconLoadedMap = {}
        this.cachePoints = [] // 缓存点位数据
        this.cacheCustomMarker = []
        this.currentCursorCoord = []

        this.editMode = null
    }

    /**
     * 加载博能地图的 script脚本
     * @param {string} url 脚本 url
     * @returns
     */
    async loadBnScript(url) {
        // const style = document.createElement('link')
        // style.href = 'http://8.137.116.133:9090/BNMap/style.css'
        // style.rel = 'stylesheet'

        // document.head.appendChild(style)

        try {
            await loadScript(url, 'BNMapJS')

            this.loadedScript = true

            if (this.watingAction.length) {
                for (const action of this.watingAction) {
                    await action()
                }
            }
        } catch (error) {
            console.warn('加载博能地图脚本失败:', error)
        }
    }

    // 执行外部调用的函数
    doAction(action) {
        if (this.loadedScript) {
            action()
            return
        }

        this.watingAction.push(action)
    }

    /**
     * 初始化博能地图实例
     * @param {*} data
     * @returns
     */
    initMap(data = {}) {
        console.log(
            '🚀[ ][ CyMapBNPlugin ][ initMap ][ window.BNMap ] =>',
            window.BNMap
        )
        if (!window.BNMap) {
            return Promise.reject(
                new Error('BNMap 未加载，请先加载 [博能地图] 脚本')
            )
        }

        this.contentmenu = new ContentMenu(document.getElementById(data.id), {
            items: []
        })

        return new Promise((resolve, reject) => {
            console.log('========	initMap  load start ========')

            window.BNMap.BFactory.Load(
                data.layers,
                // [],
                {
                    container: 'bn_map_id', // container id
                    // center: [data.x, data.y], // 初始化地图位置，可不传
                    zoom: data.zoom
                },
                // 成功回调
                (mapObj) => {
                    this.bnMap = mapObj

                    console.log('========	initMap  success ========', this.bnMap)

                    this.bindEvents()

                    resolve(mapObj)
                },
                // 错误回调
                (err) => {
                    console.log('========	initMap  error ========', err)
                    reject(err)
                }
            )

            console.log('========	initMap  load end ========')
        })
    }

    // 绑定事件
    bindEvents() {
        // 鼠标 mousedown 事件
        // this.bnMap.on('mousedown', (e) => {
        // 	console.log('单击 <mousedown> (event)', e)

        // 	let features

        // 	if (this.bnMap.getLayer(this.pointLayerID)) {
        // 		// 获取点击的要素信息
        // 		try {
        // 			features = this.bnMap.queryRenderedFeatures(e.point, {layers: [this.pointLayerID]})
        // 			console.log(features)
        // 		} catch (error) {
        // 			console.log('🚀[ ][ CyMapBNPlugin ][ bindEvents ][ error ] =>', error)
        // 		}
        // 	}

        // 	if (features?.length) {
        // 		e.preventDefault()
        // 	}

        // 	this.option.onMouseDown?.(e, features)
        // })

        this.bnMap.on('mousemove', (e) => {
            this.currentCursorCoord = [e.lngLat.lng, e.lngLat.lat]
        })

        // 鼠标点击事件
        this.bnMap.on('click', (e) => {
            //console.log('单击 <click> (event)', e)
            //console.log('contentmenu', this.contentmenu)
            this.contentmenu?.close() // 关闭右键菜单
            //console.log('单击 <click> (event)', e)

            let features

            if (this.bnMap.getLayer(this.pointLayerID)) {
                // 获取点击的要素信息
                try {
                    features = this.bnMap.queryRenderedFeatures(e.point, {
                        layers: [this.pointLayerID]
                    })
                    // console.log(features)
                } catch (error) {
                    console.log(
                        '🚀[ ][ CyMapBNPlugin ][ bindEvents ][ error ] =>',
                        error
                    )
                }
            }

            this.option.onClick?.(e, features)
        })
    }

    /**
     * 更新地图图层
     */
    updateMapLayers() {
        console.log(
            '========  updateMapLayers  pointLayerID ========',
            this.pointLayerID
        )
        if (!this.bnMap.getSource(this.pointSourceID)) {
            this.bnMap.addSource(this.pointSourceID, {
                type: 'geojson',
                data: this.pointGeojson
            })
        } else {
            this.bnMap.getSource(this.pointSourceID).setData(this.pointGeojson)
        }

        console.log(
            '========  updateMapLayers  pointSourceID ========',
            this.pointSourceID
        )

        if (!this.bnMap.getLayer(this.pointLayerID)) {
            this.bnMap.addLayer({
                id: this.pointLayerID,
                type: 'symbol',
                source: this.pointSourceID,
                layout: {
                    // 绑定图标（关联properties中的icon字段）
                    'icon-image': ['get', 'icon'],
                    // 绑定文本（关联properties中的message字段）
                    'text-field': ['get', 'message'],
                    // 文本相对于图标的位置（下方1.5个单位）
                    'text-offset': [0, 1],
                    // 文本对齐方式（顶部对齐）
                    'text-anchor': 'top',
                    // 图标大小
                    'icon-size': 1,
                    // 文本大小
                    'text-size': 14,
                    // 允许图标和文本重叠
                    'allow-overlap': true,
                    'text-allow-overlap': true,
                    // 忽略放置规则（避免文本被隐藏）
                    // 'icon-ignore-placement': true,
                    // 'text-ignore-placement': true,
                    'text-max-width': 1000
                },
                paint: {
                    // 文本颜色
                    'text-color': '#2564fc',
                    // 文本描边（增强可读性）
                    'text-halo-color': '#ffffff',
                    'text-halo-width': 1.5
                }
            })
        }
    }

    /**
     * 添加点位标记
     * @param {Object[]} markers 点位数据数组
     * @param {Boolean} isReset 是否重置点位
     * @returns {Promise} 返回 Promise 对象
     */
    async appendMarkers(markers, isReset) {
        const points = Array.isArray(markers) ? markers : [markers]

        console.log(
            '🚀[ ][ CyMapBNPlugin ][ appendMarkers ][ markers ] =>',
            points
        )

        if (!this.bnMap) {
            throw new Error('BNMap 实例未初始化，请先调用 initMap 方法')
        }

        if (isReset) {
            // 重置点位数据
            this.cachePoints = []
            this.pointGeojson.features = []
        }

        for (const item of points) {
            // 缓存点位数据
            if (
                !this.cachePoints.find(
                    (pot) => pot.device_id === item.device_id
                )
            ) {
                this.cachePoints.push(window.structuredClone(item))

                const iconName = `icon${item.model_id}`
                const svgString = this.getSvgDataUrl(item)
                // await this.registerImageIcon(svgString, iconName)
                const svgDataUrl = await svgToPng(svgString)
                await this.registerImageIcon(svgDataUrl, iconName)

                this.pointGeojson.features.push({
                    type: 'Feature',
                    properties: {
                        id: item.device_id,
                        cacheName: item.name,
                        message: item.name,
                        icon: iconName,
                        marker_id: item.id
                    },
                    geometry: {
                        type: 'Point',
                        coordinates: [item.x, item.y]
                    }
                })
            }
        }

        this.updateMapLayers()
    }

    /**
     * 添加点位标记
     * @param {Object[]} markers 点位数据数组
     * @param {Boolean} isReset 是否重置点位
     * @returns {Promise} 返回 Promise 对象
     */
    async appendDomMarkers(markers, isReset) {
        const points = Array.isArray(markers) ? markers : [markers]

        console.log(
            '🚀[ ][ CyMapBNPlugin ][ appendMarkers ][ markers ] =>',
            points
        )

        if (!this.bnMap) {
            throw new Error('BNMap 实例未初始化，请先调用 initMap 方法')
        }

        if (isReset) {
            // 重置点位数据
            this.cachePoints = []

            this.cacheCustomMarker.forEach((marker) => {
                marker?.remove?.()
            })

            this.cacheCustomMarker = []
        }

        for (const item of points) {
            // 缓存点位数据
            if (
                !this.cachePoints.find(
                    (pot) => pot.device_id === item.device_id
                )
            ) {
                this.cachePoints.push(window.structuredClone(item))

                // const iconName = `icon${item.model_id}`
                const svgString = this.getSvgDataUrl(item)
                // await this.registerImageIcon(svgString, iconName)
                const svgDataUrl = await svgToPng(svgString)

                const coords = item.lngLat || { lng: item.x, lat: item.y }

                this.createcacheCustomMarker(
                    coords,
                    {
                        iconUrl: svgDataUrl,
                        text: item.name
                    },
                    item
                )
            }
        }

        this.updateMapLayers()
    }

    // 创建一个函数来获取 SVG Data URL
    getSvgDataUrl(data, toBase64) {
        let svgString = ''
        if (data.icon) {
            svgString = `
				<svg width="${data.size}" height="${
                data.size
            }" viewBox="0 0 56 56" xmlns="http://www.w3.org/2000/svg">
						<circle fill="${data.color || '#fff'}" opacity="0.6" cx="28" cy="28" r="28"/>
						<circle fill="${data.color || '#2564fc'}" cx="28" cy="28" r="25"/>
						<path fill="#fff" d="${data.icon}"/>
				</svg>
			`

            return toBase64
                ? 'data:image/svg+xml;utf-8,' + encodeURIComponent(svgString)
                : svgString
        }

        if (data.iconfont) {
            // 如果有 iconfontPath，则使用它来生成 SVG
            if (data.iconfontPath?.length) {
                svgString = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="${
                    data.size
                }" height="${data.size}">
					<circle fill="${data.color || '#fff'}" opacity="0.6" cx="512" cy="512" r="512"/>
					<circle fill="${data.color || '#2564fc'}" cx="512" cy="512" r="500"/>
					${data.iconfontPath.map((p) => {
                        return `<path fill="#FFF" d="${p}"></path>`
                    })}
				</svg>`

                return toBase64
                    ? 'data:image/svg+xml;utf-8,' +
                          encodeURIComponent(svgString)
                    : svgString
            }

            const iconElement = document.querySelector(`#${data.iconfont}`)
            const iconPath = iconElement?.querySelectorAll('path')

            iconPath?.forEach((item) => {
                // item.setAttribute('fill', data.color)
                item.setAttribute('fill', '#FFF')
                item.setAttribute('transform', 'translate(400,400)')
            })

            if (!iconElement) return null

            svgString = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1848 1848" width="${
                data.size
            }" height="${data.size}">
				<circle fill="${data.color || '#fff'}" opacity="0.6" cx="924" cy="924" r="924"/>
				<circle fill="${data.color || '#2564fc'}" cx="924" cy="924" r="800"/>
				${iconElement.innerHTML}
			</svg>`

            return toBase64
                ? 'data:image/svg+xml;utf-8,' + encodeURIComponent(svgString)
                : svgString
        }
    }

    /**
     * 注册图标
     * @param {*} svgDataUrl
     * @param {*} iconName
     * @returns
     */
    async registerImageIcon(svgDataUrl, iconName) {
        if (this.pointIconLoadedMap[iconName]) {
            return Promise.resolve() // 如果已经加载过，直接返回
        }

        return new Promise((resolve, reject) => {
            this.bnMap.loadImage(svgDataUrl, (error, image) => {
                if (error) {
                    console.error(`加载图片${iconName}失败:`, error)
                    reject(error)
                    return
                }

                // 注册图片
                this.bnMap.addImage(iconName, image)
                this.pointIconLoadedMap[iconName] = true // 标记为已加载

                resolve()
            })
        })
    }

    /**
     * 开始移动点位
     * @param {*} point
     */
    // startMovePoint (point = {}) {

    // }

    /**
     * 创建自定义标记
     * @param {*} coords
     * @param {*} options
     * @returns
     */
    createcacheCustomMarker(coords, options = {}, data = {}) {
        const {
            iconUrl, // 图标图片URL
            iconSize = 36, // 图标尺寸 [宽, 高]
            text, // 文本内容
            textColor = '#2564fc', // 文本颜色
            textSize = 14, // 文本大小
            offset = [0, 0] // 文本相对于图标的偏移 [x, y]
        } = options

        // 1. 创建容器元素（包含图标和文本）
        const container = document.createElement('div')
        // container.style.position = 'relative'
        // container.style.width = `${iconSize}px`
        container.style.display = 'flex'
        container.style.flexDirection = 'column'
        container.style.alignItems = 'center'
        container.style.gap = '4px'
        container.style.height = `${iconSize + 24}px` // 预留文本空间
        // container.style.transform = 'translate(-50%, -50%)'
        // 2. 创建图标元素
        const icon = document.createElement('div')
        icon.style.width = `${iconSize}px`
        icon.style.flex = `${iconSize}px 0 0`
        icon.style.backgroundImage = `url(${iconUrl})`
        icon.style.backgroundSize = '100% 100%'
        icon.style.cursor = 'pointer'
        container.appendChild(icon)
        // 3. 创建文本元素
        if (text) {
            const textEl = document.createElement('div')
            textEl.textContent = text
            // textEl.style.position = 'absolute'
            // textEl.style.left = '50%'
            //textEl.style.top = `${iconSize[1] + offset[1]}px`
            textEl.style.color = textColor
            textEl.style.fontSize = `${textSize}px`
            textEl.style.whiteSpace = 'nowrap' // 文本不折行
            textEl.style.textAlign = 'center'
            // textEl.style.width = '100%'
            // textEl.style.transform = 'translateX(-50%)'
            container.appendChild(textEl)
        }

        // 4. 创建BNMarker实例并添加到地图
        const marker = new window.BNMap.BNMarker({
            element: container,
            draggable: true
        })
            // .setLngLat({ lng: coords[1], lat: coords[0] }) // 设置坐标
            .setLngLat(coords) // 设置坐标
            // .setAnchor(0.5, 0.5)
            .addTo(this.bnMap) // 添加到地图

        // 5. 绑定点击事件
        container.onclick = (event) => {
            // console.log('🚀[ ][ CyMapBNPlugin ][ createcacheCustomMarker ][ event ] =>', event)
            event.stopPropagation()
            const finalLngLat = marker.getLngLat()
            const finalCoords = [finalLngLat.lng, finalLngLat.lat] // 最终坐标
            // console.log(`[${text}] 点位点击：`, marker, finalCoords)
            this.option.onDomMarkerClick?.(event, marker, finalCoords) // 执行外部传入的回调函数
        }

        container.oncontextmenu = (event) => {
            event.preventDefault() // 阻止默认右键菜单行为
            event.stopPropagation()

            if (!this.option.useOperation) {
                return
            }

            console.log(
                '🚀[ ][ CyMapBNPlugin ][ createcacheCustomMarker ][ event ] =>',
                event
            )

            const finalLngLat = marker.getLngLat()
            const finalCoords = [finalLngLat.lng, finalLngLat.lat] // 最终坐标

            //设置菜单选项并打开菜单
            this.contentmenu.setMenuOptions({
                items: [
                    {
                        id: 1,
                        text: '删除点位',
                        callback: () => {
                            this.option.onContextMenu?.(
                                'delete',
                                data,
                                marker,
                                finalCoords
                            ) // 执行外部传入的回调函数
                        }
                    }
                ]
            })

            // 延时打开菜单，否则会触发拖拽元素
            setTimeout(() => {
                this.contentmenu.open([event.clientX, event.clientY])
            }, 100)

            return
        }

        // 3. 监听拖动相关事件
        // 拖动开始
        marker.on('dragstart', () => {
            container.style.opacity = '0.7' // 拖动时半透明效果
            console.log(`[${text}] 开始拖动`)
        })

        // 拖动过程中（可选）
        marker.on('drag', () => {
            // const currentLngLat = marker.getLngLat()
            // console.log(`[${text}] 拖动中：`, [
            //     currentLngLat.lng,
            //     currentLngLat.lat
            // ])
        })

        // 拖动结束（核心监听）
        marker.on('dragend', () => {
            container.style.opacity = '1' // 恢复不透明度
            const finalLngLat = marker.getLngLat()
            const finalCoords = [finalLngLat.lng, finalLngLat.lat] // 最终坐标
            console.log(`[${text}] 拖动结束，新坐标：`, marker, finalCoords)
            this.option.onDragEnd?.(finalCoords, marker, data) // 执行外部传入的回调函数
        })

        this.cacheCustomMarker.push(marker)

        return marker
    }

    // 设置点位名称是否可见
    visibleText(visible) {
        this.pointGeojson.features.forEach((feature) => {
            if (feature.properties) {
                feature.properties.message = visible
                    ? feature.properties.cacheName
                    : ''
            }
        })

        this.bnMap.getSource(this.pointSourceID).setData(this.pointGeojson)
    }

    /**
     * 根据 id 显示点位
     */
    filterFeatures(pointIds) {
        const idMap = pointIds.reduce((map, id) => {
            map[id] = 1

            return map
        }, {})

        return this.cachePoints.filter((point) => idMap[point.device_id])
    }

    /**
     * 根据 id 显示点位
     */
    visibleFeatures(pointIds) {
        const features = this.filterFeatures(pointIds)

        this.pointGeojson.features = features.map((item) => {
            const iconName = `icon${item.model_id}`

            return {
                type: 'Feature',
                properties: {
                    id: item.device_id,
                    cacheName: item.name,
                    message: item.name,
                    icon: iconName
                },
                geometry: {
                    type: 'Point',
                    coordinates: [item.x, item.y]
                }
            }
        })

        this.bnMap.getSource(this.pointSourceID).setData(this.pointGeojson)
    }

    /**
     * 根据 id 显示点位
     */
    visiblePoint(id) {
        if (
            this.pointGeojson.features.find((item) => item.properties.id === id)
        ) {
            return
        }

        const feature = this.cachePoints.find((point) => point.device_id === id)

        if (!feature) {
            return
        }

        const iconName = `icon${feature.model_id}`

        this.pointGeojson.features.push({
            type: 'Feature',
            properties: {
                id: feature.device_id,
                cacheName: feature.name,
                message: feature.name,
                icon: iconName
            },
            geometry: {
                type: 'Point',
                coordinates: [feature.x, feature.y]
            }
        })

        this.bnMap.getSource(this.pointSourceID).setData(this.pointGeojson)
    }

    /**
     * 根据 id 移除点位
     */
    hiddenPoint(id) {
        if (
            !this.pointGeojson.features.find(
                (item) => item.properties.id === id
            )
        ) {
            return
        }

        this.pointGeojson.features = this.pointGeojson.features.filter(
            (item) => item.properties.id !== id
        )

        this.bnMap.getSource(this.pointSourceID).setData(this.pointGeojson)
    }

    /**
     * 移动到 feature 的位置
     */
    moveToFeature(id) {
        const feature = this.cachePoints.find((item) => item.device_id === id)

        if (!feature) {
            console.log(
                '🚀[ ][ CyMap ][ moveToFeature ][ feature ] =>',
                feature
            )
            return
        }

        this.bnMap.setCenter([feature.x, feature.y]) // 设置地图中心点
    }

    /**
     * 开启编辑模式
     */
    // startEditMode() {
    // 	if (!this.bnMap) {
    // 		throw new Error('BNMap 实例未初始化，请先调用 initMap 方法')
    // 	}

    // 	this.stopEditMode()

    // 	this.editMode = new window.BNMap.BNEdit(this.bnMap, {layerId: '1'})
    // 	console.log('🚀[ ][ CyMapBNPlugin ][ startEditMode ][ this.editMode ] =>', this.bnMap.getCenter())
    // 	this.editMode.startEdit('1')
    // 	// this.editMode.startEdit(this.pointLayerID)
    // 	// this.editMode.initLayer('1')

    // 	console.log('编辑模式已开启')
    // }

    /**
     * 结束编辑模式
     */
    // stopEditMode() {
    // 	if (this.editMode) {
    // 		this.editMode.destroy()
    // 		this.editMode = null
    // 	}
    // }

    /**
     * 获取 BNMap 实例
     * @returns {BNMap} 返回 BNMap 实例
     */
    getInstance() {
        if (this.bnMap) {
            return this.bnMap
        }

        throw new Error('BNMap 实例未初始化，请先调用 initMap 方法')
    }
}

export default CyMapBNPlugin

/**
 * @description 异步加载博能地图
 * @param {*} data
 * @returns
 */
// export function loadBNMap(data) {
//     return new Promise((resolve, reject) => {
//         BNMap.BFactory.Load(
//             data.layers,
//             {
//                 container: 'bn_map_id', // container id
//                 // center: [data.x, data.y], // 初始化地图位置，可不传
//                 zoom: data.zoom
//             },
//             // 成功回调
//             (mapObj) => {
//                 resolve(mapObj)
//             },
//             // 错误回调
//             (err) => {
//                 reject(err)
//             }
//         )
//     })
// }
/**
 * @description 批量加载点位
 * @param {*} map
 * @param {*} markers
 */
// export async function loadMarkers(map, markers) {
//     console.log('🚀[ ][ loadMarkers ][ markers ] =>', markers)
//     const geojson = { type: 'FeatureCollection', features: [] }
//     const imagePromises = [] // 存储所有图片加载的Promise

//     // 遍历标记，收集图片加载任务
//     markers.forEach(async (item, index) => {
//         const iconName = `icon${index}`
//         const svgString = buildSvgString(item)
//         const svgDataUrl = await svgToPng(svgString)
//         await loadAndRegisterImage(map, svgDataUrl, iconName)
//         // 示例2：使用SVG作为图标（无需额外图片）
//         // const marker2 = createcacheCustomMarker(
//         //     map,
//         //     [item.x * 1, item.y * 1],
//         //     {
//         //         iconUrl: svgDataUrl, // 使用SVG DataURL
//         //         iconSize: [25, 25],
//         //         text: item.name,
//         //         textColor: item.color
//         //     },
//         //     (finalCoords, marker) => {
//         //         console.log('回调接收的最终坐标：', finalCoords)
//         //         // 可在此处执行保存逻辑（如提交到后端）
//         //         // saveCoordinates(finalCoords);
//         //     }
//         // )
//         // marker2.setDraggable(true)
//         // 3. 创建单点GeoJSON数据
//         const geojson = {
//             type: 'FeatureCollection',
//             features: [
//                 {
//                     type: 'Feature',
//                     properties: {
//                         message: item.name, // 文本内容
//                         icon: iconName // 关联图标名称
//                     },
//                     geometry: {
//                         type: 'Point',
//                         coordinates: [item.x * 1, item.y * 1] // 经纬度
//                     }
//                 }
//             ]
//         }
//         const layerId = `layer${index}`
//         // 4. 添加数据源
//         map.addSource(layerId, {
//             type: 'geojson',
//             data: geojson
//         })

//         map.addLayer({
//             id: layerId,
//             type: 'symbol',
//             source: layerId,
//             layout: {
//                 // 绑定图标（关联properties中的icon字段）
//                 'icon-image': ['get', 'icon'],
//                 // 绑定文本（关联properties中的message字段）
//                 'text-field': ['get', 'message'],
//                 // 文本相对于图标的位置（下方1.5个单位）
//                 'text-offset': [0, 1],
//                 // 文本对齐方式（顶部对齐）
//                 'text-anchor': 'top',
//                 // 图标大小
//                 'icon-size': 1,
//                 // 文本大小
//                 'text-size': 14,
//                 // 允许图标和文本重叠
//                 'allow-overlap': true,
//                 'text-allow-overlap': true,
//                 // 忽略放置规则（避免文本被隐藏）
//                 'icon-ignore-placement': true,
//                 'text-ignore-placement': true,
//                 'text-max-width': 1000
//             },
//             paint: {
//                 // 文本颜色
//                 'text-color': item.color || '#2564fc',
//                 // 文本描边（增强可读性）
//                 'text-halo-color': '#ffffff',
//                 'text-halo-width': 1.5
//             }
//         })

//         // // 立即创建GeoJSON要素（不依赖图片加载）
//         // geojson.features.push({
//         //     type: 'Feature',
//         //     properties: { message: item.name, icon: iconName },
//         //     geometry: {
//         //         type: 'Point',
//         //         coordinates: [Number(item.x), Number(item.y)]
//         //     }
//         // })

//         // // 异步加载并注册图片，收集Promise
//         // const promise = (async () => {
//         //     const svgString = buildSvgString(item)
//         //     const svgDataUrl = await svgToPng(svgString)
//         //     await loadAndRegisterImage(map, svgDataUrl, iconName)
//         // })()
//         // imagePromises.push(promise)
//     })
//     return
//     // 等待所有图片注册完成
//     await Promise.all(imagePromises)
//     map.addSource('points', { type: 'geojson', data: geojson })
//     map.addLayer({
//         id: 'points',
//         type: 'symbol',
//         source: 'points',
//         layout: {
//             // 根据属性中指定字段展示图片
//             'icon-image': ['get', 'icon'],
//             // 获取属性中的文本进行展示
//             'text-field': ['get', 'message'],
//             // 文本x、y轴偏移值
//             'text-offset': [0, 1.5],
//             'text-anchor': 'top',
//             'allow-overlap': true, // 允许图标重叠
//             overlap: true, // 允许文本重叠
//             'icon-size': 1, // 图片缩放比例
//             'text-size': 14,
//             'icon-ignore-placement': true, // 忽略放置规则
//             'text-ignore-placement': true, // 忽略放置规则
//             // 添加以下属性设置文本最大宽度
//             'text-max-width': 1000
//         },
//         paint: {
//             'text-color': '#FF0000', // 设置文本颜色为红色
//             'text-halo-color': '#FFFFFF', // 设置文本的外边框颜色
//             'text-halo-width': 2 // 设置文本的外边框宽度
//         }
//     })
// }
// function createcacheCustomMarker(map, coords, options) {
//     const {
//         iconUrl, // 图标图片URL
//         iconSize, // 图标尺寸 [宽, 高]
//         text, // 文本内容
//         textColor, // 文本颜色
//         textSize, // 文本大小
//         offset = [0, 0] // 文本相对于图标的偏移 [x, y]
//     } = options

//     // 1. 创建容器元素（包含图标和文本）
//     const container = document.createElement('div')
//     //container.style.position = 'relative'
//     container.style.width = `${iconSize[0]}px`
//     container.style.height = `${iconSize[1] + 20}px` // 预留文本空间
//     container.style.transform = 'translate(-50%, -50%)'
//     // 2. 创建图标元素
//     const icon = document.createElement('div')
//     icon.style.width = `${iconSize[0]}px`
//     icon.style.height = `${iconSize[1]}px`
//     icon.style.backgroundImage = `url(${iconUrl})`
//     icon.style.backgroundSize = '100% 100%'
//     icon.style.cursor = 'pointer'
//     container.appendChild(icon)
//     // 3. 创建文本元素
//     if (text) {
//         const textEl = document.createElement('div')
//         textEl.textContent = text
//         //textEl.style.position = 'absolute'
//         //textEl.style.left = `${offset[0]}px`
//         //textEl.style.top = `${iconSize[1] + offset[1]}px`
//         textEl.style.color = textColor
//         textEl.style.fontSize = `${textSize}px`
//         textEl.style.whiteSpace = 'nowrap' // 文本不折行
//         textEl.style.textAlign = 'center'
//         textEl.style.width = '100%'
//         container.appendChild(textEl)
//     }

//     // 4. 创建BNMarker实例并添加到地图
//     const marker = new BNMap.BNMarker(container)
//         // .setLngLat({ lng: coords[1], lat: coords[0] }) // 设置坐标
//         .setLngLat(coords) // 设置坐标
//         // .setAnchor(0.5, 0.5)
//         .addTo(map) // 添加到地图

//     // 3. 监听拖动相关事件
//     // 拖动开始
//     marker.on('dragstart', () => {
//         container.style.opacity = '0.7' // 拖动时半透明效果
//         console.log(`[${text}] 开始拖动`)
//     })

//     // 拖动过程中（可选）
//     marker.on('drag', () => {
//         const currentLngLat = marker.getLngLat()
//         // console.log(`[${text}] 拖动中：`, [
//         //     currentLngLat.lng,
//         //     currentLngLat.lat
//         // ])
//     })

//     // 拖动结束（核心监听）
//     marker.on('dragend', () => {
//         container.style.opacity = '1' // 恢复不透明度
//         const finalLngLat = marker.getLngLat()
//         const finalCoords = [finalLngLat.lng, finalLngLat.lat] // 最终坐标
//         console.log(`[${text}] 拖动结束，新坐标：`, finalCoords)

//         // 执行外部传入的回调函数，返回最终坐标
//         if (typeof onDragEnd === 'function') {
//             onDragEnd(finalCoords, marker)
//         }
//     })
//     return marker
// }
/**
 * @description 异步注册加载点位图标
 * @param {*} map
 * @param {*} svgDataUrl
 * @param {*} iconName
 * @returns
 */
// export function loadAndRegisterImage(map, svgDataUrl, iconName) {
//     return new Promise((resolve, reject) => {
//         map.loadImage(svgDataUrl, (error, image) => {
//             if (error) {
//                 console.error(`加载图片${iconName}失败:`, error)
//                 reject(error)
//                 return
//             }
//             // 注册图片
//             map.addImage(iconName, image)
//             resolve()
//         })
//     })
// }

/**
 * @description 转换svgToPng
 * @param {*} item
 * @returns
 */
// export function buildSvgString(item) {
//     return `<svg width="36" height="36" viewBox="0 0 56 56" xmlns="http://www.w3.org/2000/svg">
//         <circle fill="${
//             item.color || '#fff'
//         }" opacity="0.6" cx="28" cy="28" r="28"/>
//         <circle fill="${item.color || '#2564fc'}" cx="28" cy="28" r="25"/>
//         <path fill="#fff" d="${item.icon}"/>
//     </svg>`
// }

/**
 * @description 转换svgToPng
 * @param {*} svgString
 * @param {*} width
 * @param {*} height
 * @returns
 */
export function svgToPng(svgString, width = 25, height = 25) {
    return new Promise((resolve, reject) => {
        // 1. 创建SVG Blob对象
        const svgBlob = new Blob([svgString], {
            type: 'image/svg+xml;charset=utf-8'
        })
        const svgUrl = URL.createObjectURL(svgBlob)

        // 2. 创建图像对象加载SVG
        const img = new Image()
        img.crossOrigin = 'anonymous' // 允许跨域加载

        // 3. 加载成功后绘制到Canvas
        img.onload = () => {
            // 清理资源
            URL.revokeObjectURL(svgUrl)

            // 创建Canvas
            const canvas = document.createElement('canvas')
            canvas.width = width
            canvas.height = height
            const ctx = canvas.getContext('2d')

            // 清除画布并绘制图像
            ctx.clearRect(0, 0, width, height)
            ctx.drawImage(img, 0, 0, width, height)

            try {
                // 转换为PNG
                const pngDataUrl = canvas.toDataURL('image/png')
                resolve(pngDataUrl)
            } catch (error) {
                reject(new Error('Canvas转换PNG失败: ' + error.message))
            }
        }

        // 4. 处理加载错误
        img.onerror = () => {
            URL.revokeObjectURL(svgUrl)
            reject(new Error('SVG加载失败，请检查SVG格式是否正确'))
        }

        // 5. 处理加载超时
        const timeoutId = setTimeout(() => {
            URL.revokeObjectURL(svgUrl)
            reject(new Error('SVG加载超时'))
        }, 5000)

        // 开始加载SVG
        img.src = svgUrl
    })
}

/**
 * 右键菜单
 */
class ContentMenu {
    show_ = false

    menu_ = null

    object_ = {}

    /**
     *
     * @param {HTMLElement} target
     * @param {Object} opt_options
     */
    constructor(target, opt_options) {
        this.options_ = opt_options || {}
        this.target = target
    }

    init() {
        let now = document.getElementById('ol-contentmenu')
        if (now) {
            this.target.removeChild(now)
        }
        this.menu_ = document.createElement('div')
        this.menu_.id = 'ol-contentmenu'
        this.menu_.className = 'ol-contentmenu'
        this.menu_.style.visibility = 'hidden'

        if (Array.isArray(this.options_.items)) {
            const ul = document.createElement('ul')
            ul.className = 'ol-contentmenu-ul'
            this.menu_.appendChild(ul)

            this.options_.items.forEach((item) => {
                const li = document.createElement('li')
                li.className = 'ol-contentmenu-item'
                li.innerText = item.text
                li.style.padding = '3px 5px'
                li.onclick = (e) => {
                    this.close()
                    item.callback({
                        target: e,
                        ...this.object_
                    })
                }
                ul.appendChild(li)
            })
        }

        this.target.appendChild(this.menu_)
    }

    setMenuOptions(opt_options) {
        this.options_ = opt_options || {}
        this.init()
    }

    addItem(opt_options) {
        const options = opt_options || {
            text: 'item',
            callback: (e) => {}
        }
        const item = document.createElement('div')
        item.className = 'ol-contentmenu-item'
        item.text = options.text
        item.onclick = options.callback
        return item
    }

    open(pixel, options) {
        this.object_ = options
        this.menu_.style.visibility = 'visible'
        this.menu_.style.position = 'fixed'
        this.menu_.style.zIndex = 99999
        this.menu_.style.top = pixel[1] + 'px'
        this.menu_.style.left = pixel[0] + 'px'
    }

    close() {
        if (this.menu_) {
            this.menu_.style.visibility = 'hidden'
        }
    }
}
